package ioc

import (
	"fmt"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/plugin/opentelemetry/tracing"
	"gorm.io/plugin/prometheus"
	"jk-time/webook/internal/dao"
	"jk-time/webook/pkg/gormx/callbacks"
	"jk-time/webook/pkg/gormx/connpool"
)

type SrcDB *gorm.DB
type DstDB *gorm.DB

func InitSRC() SrcDB {
	return initDB("src")
}
func InitDST() DstDB {
	return initDB("dst")
}
func InitDoubleWritePool(src SrcDB, dst DstDB) *connpool.DoubleWritePool {
	pattern := viper.GetString("migrator.pattern")
	return connpool.NewDoubleWritePool(src.ConnPool, dst.ConnPool, pattern)
}
func InitBizDB(p *connpool.DoubleWritePool) *gorm.DB {
	db, err := gorm.Open(mysql.New(mysql.Config{
		Conn: p,
	}))
	if err != nil {
		panic(err)
	}
	return db
}
func initDB(key string) *gorm.DB {
	user := viper.GetString(fmt.Sprintf("db.%s.user", key))
	password := viper.GetString(fmt.Sprintf("db.%s.password", key))
	host := viper.GetString(fmt.Sprintf("db.%s.host", key))
	dbs := viper.GetString(fmt.Sprintf("db.%s.dbs", key))

	sqlConfig := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc"+
		"=Local", user, password, host, dbs)
	db, err := gorm.Open(mysql.Open(sqlConfig))
	if err != nil {
		panic(err)
	}

	err = db.Use(prometheus.New(prometheus.Config{
		DBName:          "webook" + key,
		RefreshInterval: 15,
		StartServer:     false,
		MetricsCollector: []prometheus.MetricsCollector{
			&prometheus.MySQL{
				VariableNames: []string{"thread_running"},
			},
		},
	}))
	if err != nil {
		zap.L().Error("gorm监控失败:", zap.Error(err))
	}

	callback := prome.NewCallback(
		"jk_time",
		"webook",
		"gorm_query_time"+key,
		"统计gorm的执行时间",
		"gorm-"+key)

	err = db.Use(callback)
	if err != nil {
		zap.L().Error("gorm callback监控失败:", zap.Error(err))
	}

	db.Use(tracing.NewPlugin(tracing.WithDBName("webook"), tracing.WithQueryFormatter(func(query string) string {
		zap.L().Debug("", zap.String("query", query))
		return query
	}),
		//不要记录metrics
		tracing.WithoutMetrics(),
		//不要查询参数
		tracing.WithoutQueryVariables(),
	))

	err = dao.InitTables(db)
	if err != nil {
		panic(err)
	}
	return db
}
